﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Configuration;
using Slf.Config;

namespace SLF.Test.Config
{
  [TestClass]
  public class SlfConfigurationTest
  {
    /// <summary>
    /// Simple positive test, ensure that the factory name and type are properly mapped 
    /// from the configuration XML file.
    /// </summary>
    [TestMethod]
    [DeploymentItem("TestData/FixtureOne.exe")]
    [DeploymentItem("TestData/FixtureOne.exe.config")]
    public void LoadFromConfig_CompleteConfigruation_CorrectlyLoaded()
    {
      Configuration config = ConfigurationManager.OpenExeConfiguration("FixtureOne.exe");
      SlfConfigurationSection slfConfig = (SlfConfigurationSection)config.GetSection("slf");

      Assert.AreEqual(2, slfConfig.Factories.Count);
      Assert.AreEqual("nameOne", slfConfig.Factories[0].Name);
      Assert.AreEqual("nameTwo", slfConfig.Factories[1].Name);
      Assert.AreEqual("typeOne", slfConfig.Factories[0].Type);
      Assert.AreEqual("typeTwo", slfConfig.Factories[1].Type);
    }

    /// <summary>
    /// Check that a configuration file which contains no 
    /// factories is loaded correctly
    /// </summary>
    [TestMethod]
    [DeploymentItem("TestData/FixtureThree.exe")]
    [DeploymentItem("TestData/FixtureThree.exe.config")]
    public void LoadFromConfig_NoFactories_CorrectlyLoaded()
    {
      Configuration config = ConfigurationManager.OpenExeConfiguration("FixtureThree.exe");
      SlfConfigurationSection slfConfig = (SlfConfigurationSection)config.GetSection("slf");

      Assert.AreEqual(0, slfConfig.Factories.Count);
    }

    /// <summary>
    /// Test factory elements with missing properties. 
    /// 
    /// NOTE: while the factory.Type property is considered mandatory
    /// indicating this with 'IsRequired = true' on the property 
    /// metadata causes the parsing for the entire configuration section
    /// to fail.
    /// </summary>
    [TestMethod]
    [DeploymentItem("TestData/FixtureTwo.exe")]
    [DeploymentItem("TestData/FixtureTwo.exe.config")]
    public void LoadFromConfig_MissingProperties_CorrectlyLoaded()
    {
      Configuration config = ConfigurationManager.OpenExeConfiguration("FixtureTwo.exe");
      SlfConfigurationSection slfConfig = (SlfConfigurationSection)config.GetSection("slf");

      Assert.AreEqual(2, slfConfig.Factories.Count);
      Assert.AreEqual(string.Empty, slfConfig.Factories[0].Name);
      Assert.AreEqual("nameTwo", slfConfig.Factories[1].Name);
      Assert.AreEqual("typeOne", slfConfig.Factories[0].Type);
      Assert.AreEqual(string.Empty, slfConfig.Factories[1].Type);
    }


    /// <summary>
    /// Simple positive test, ensure that the factory name and type are properly mapped 
    /// from the configuration XML file.
    /// </summary>
    [TestMethod]
    [DeploymentItem("TestData/CustomFactoryData.exe")]
    [DeploymentItem("TestData/CustomFactoryData.exe.config")]
    public void Parsing_Factory_With_Custom_Content_Should_Provide_Inner_Xml()
    {
      Configuration config = ConfigurationManager.OpenExeConfiguration("CustomFactoryData.exe");
      SlfConfigurationSection slfConfig = (SlfConfigurationSection)config.GetSection("slf");

      Assert.AreEqual(2, slfConfig.Factories.Count);
      FactoryConfigurationElement simpleFactory = slfConfig.Factories[0];
      FactoryConfigurationElement complexFactory = slfConfig.Factories[1];

      Assert.AreEqual("simple", simpleFactory.Name);
      Assert.AreEqual("complex", complexFactory.Name);

      Assert.AreEqual("simple data", simpleFactory.FactoryData);

      XElement element = XElement.Parse(complexFactory.FactoryData);
      Assert.AreEqual("child", element.Name);
      Assert.AreEqual("bar", element.Attribute("foo").Value);

      XElement subElement = element.Element("subchild");
      Assert.IsNotNull(subElement, "Sub element not parsed");
      Assert.AreEqual("foobar", subElement.Value);
    }

  }
}
